package source;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import source.DataSource;
import source.DataSourceListener;

/**
 * 07-09 02:19 Added support for stop/start of data gathering. Needs refactor (this class creates an instance of itself...)
 * @author Michal
 *
 */
public class Simulator extends Thread implements DataSource {
	private List<DataSourceListener> listeners;
	private volatile boolean gather;

	Simulator workerThread = null;

	public Simulator() {
		listeners = new ArrayList<DataSourceListener>();
	}
	
	public Simulator(List<DataSourceListener> listeners) {
		this.listeners = listeners;
	}

	public static byte[] toByta(long data) {
		return new byte[] { (byte) ((data >> 56) & 0xff),
				(byte) ((data >> 48) & 0xff), (byte) ((data >> 40) & 0xff),
				(byte) ((data >> 32) & 0xff), (byte) ((data >> 24) & 0xff),
				(byte) ((data >> 16) & 0xff), (byte) ((data >> 8) & 0xff),
				(byte) ((data >> 0) & 0xff), };
	}

	public static byte[] toByta(long[] data) {
		if (data == null)
			return null;
		// ----------
		byte[] byts = new byte[data.length * 8];
		for (int i = 0; i < data.length; i++)
			System.arraycopy(toByta(data[i]), 0, byts, i * 8, 8);
		return byts;
	}

	public static byte[] toByta(double data) {
		return toByta(Double.doubleToRawLongBits(data));
	}

	@Override
	public void addListner(DataSourceListener listener) {
		listeners.add(listener);
	}

	@Override
	public void startGatheringData() {
		if (workerThread != null) {
			workerThread.setGather(false);
		}
		workerThread = new Simulator(listeners);
		workerThread.setGather(true);
		workerThread.start();
	}

	@Override
	public void stopGatheringData() {
		if (workerThread != null) {
			workerThread.setGather(false);
		}
	}

	public static Random rand = new Random();

	public double getRandom() {
		return rand.nextDouble();
	}

	private void notifyObservers(RawData data) {
		for (DataSourceListener listener : listeners) {
			if (listener != null) {
				listener.notify(data);
			}
		}
	}

	@Override
	public void run() {
		super.run();
		while (isGather()) {
			RawDataImpl data = new RawDataImpl();
			data.setData((getRandom() * 30) + "");
			notifyObservers(data);
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	@Override
	public String getConfigId() {
		return "Simulator";
	}

	public void setGather(boolean gather) {
		this.gather = gather;
	}

	public boolean isGather() {
		return gather;
	}
}
